package com.android.support.lib.universal.sdk.weixin.wxapi;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.xmlpull.v1.XmlPullParser;

import com.android.support.lib.universal.http.NotifyUrl;
import com.android.support.lib.universal.util.Utilmac;
import com.android.support.lib.universal.util.Utilnum;
import com.android.support.lib.universal.util.Utilstr;

import android.content.Context;
import android.util.Log;
import android.util.Xml;


/**
 * 获取微信参数
 * 
 * @author 彭治铭
 *
 */
public class ParamUtil {

	Utilmac mac = new Utilmac();
	Utilstr str = new Utilstr();
	Utilnum num = new Utilnum();// 对微信价格进行处理

	/**
	 * 统一下单 参数设置
	 * 
	 * @param context
	 * @param trade_type
	 *            默认为"APP","NATIVE"主要用于网页扫码支付。
	 * @return
	 */
	public String genProductArgs_Unifiedorder(Context context, String trade_type) {

		List<NameValuePair> packageParamses = new LinkedList<NameValuePair>();
		packageParamses.add(new BasicNameValuePair("appid", Constants.APP_ID));// 必须
		packageParamses.add(new BasicNameValuePair("mch_id",
				Constants.PARTNER_ID));// 微信支付分配的商户号,必须
		packageParamses.add(new BasicNameValuePair("device_info", mac
				.getDeviceId(context)));// 终端设备号，一般填1000即可非必须
		packageParamses.add(new BasicNameValuePair("nonce_str", genNonceStr()));// 随机字符串，不长于32位，必须

		// packageParamses.add(new BasicNameValuePair("trade_type", "APP"));
		// 开放平台app支付。
		// 交易类型,取值如下：JSAPI，NATIVE，APP.必须
		if (trade_type != null && !trade_type.trim().equals("")) {
			packageParamses
					.add(new BasicNameValuePair("trade_type", trade_type));// 公众号开发支付。JSAPI支付必须传openid
		} else {
			packageParamses.add(new BasicNameValuePair("trade_type", "APP"));
		}

		packageParamses.add(new BasicNameValuePair("body",
				WeixinManager.mPayTheGoodName));// 商品名，必须
		packageParamses.add(new BasicNameValuePair("notify_url",
				NotifyUrl.notify_url_wxapi));// 服务器回调地址，必须为直接可访问的url，不能携带参数。只是能够直接打得开，必不可少。
		packageParamses.add(new BasicNameValuePair("out_trade_no", NotifyUrl
				.getOutTradeNo(context)));// 商户订单号,32个字符内、可包含字母.每次订单号不能相同。必不可少
		packageParamses.add(new BasicNameValuePair("spbill_create_ip", mac
				.getLocalHostIp4()));// 终端IP(APP和网页支付提交用户端ip)， 必须

		packageParamses.add(new BasicNameValuePair("total_fee", num
				.StrToInt(WeixinManager.mPayTheMoney)));// 多少钱，数值1对应微信一分钱。必须只能是整数。必不可少

		packageParamses.add(new BasicNameValuePair("attach", "上海尚热网络科技有限公司"));// 附加数据,非必须

		String sign = createSign(packageParamses);
		packageParamses.add(new BasicNameValuePair("sign", sign));// 签名, 必须

		return StringToXml(packageParamses);
	}

	/**
	 * 查询订单 参数设置
	 * 
	 * @return
	 */
	public String genProductArgs_Query(Context context) {

		List<NameValuePair> packageParamses = new LinkedList<NameValuePair>();
		packageParamses.add(new BasicNameValuePair("appid", Constants.APP_ID));// 必须
		packageParamses.add(new BasicNameValuePair("mch_id",
				Constants.PARTNER_ID));// 微信支付分配的商户号,必须
		packageParamses.add(new BasicNameValuePair("out_trade_no", NotifyUrl
				.getOutTradeNo(context)));// 商户订单号,32个字符内、可包含字母.每次订单号不能相同。必不可少
		packageParamses.add(new BasicNameValuePair("nonce_str", genNonceStr()));// 随机字符串，不长于32位，必须

		String sign = createSign(packageParamses);
		packageParamses.add(new BasicNameValuePair("sign", sign));// 签名, 必须

		return StringToXml(packageParamses);
	}

	/**
	 * 获取微信签名参数 sign
	 * 
	 * @param params
	 *            微信所有参数，除sign外的所有参数
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public String createSign(List<NameValuePair> params) {
		SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
		for (int i = 0; i < params.size(); i++) {
			parameters.put(params.get(i).getName(), params.get(i).getValue());
		}
		StringBuffer sb = new StringBuffer();
		Set<?> es = parameters.entrySet();// 所有参与传参的参数按照accsii排序（升序）
		Iterator<?> it = es.iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			String k = (String) entry.getKey();
			Object v = entry.getValue();
			if (null != v && !"".equals(v) && !"sign".equals(k)
					&& !"key".equals(k)) {
				sb.append(k + "=" + v + "&");
			}
		}
		sb.append("key=" + Constants.PARTNER_KEY);// 商户密钥
		String sign = MD5.getMessageDigest(sb.toString().getBytes())
				.toUpperCase();
		return sign;
	}

	/**
	 * 获取 nonce_str(随机字符串，不长于32位)
	 * 
	 * @return
	 */
	public String genNonceStr() {
		Random random = new Random();
		return MD5.getMessageDigest(String.valueOf(random.nextInt(10000))
				.getBytes());
	}

	/**
	 * 将键值对转化成xml格式
	 * 
	 * @param packageParams
	 *            微信所有参数，记得是所有参数
	 * @return
	 */
	public String StringToXml(List<NameValuePair> packageParams) {
		StringBuilder sb = new StringBuilder();
		sb.append("<xml>");
		for (int i = 0; i < packageParams.size(); i++) {
			sb.append("\n<" + packageParams.get(i).getName() + ">");
			sb.append(packageParams.get(i).getValue());
			sb.append("</" + packageParams.get(i).getName() + ">");
		}
		sb.append("\n</xml>");
		return sb.toString();
	}

	/**
	 * 返回Map数据集合
	 * 
	 * @param xmlContent
	 *            xml文本内容
	 * @param paramsName
	 *            xml里的参数集合
	 * @param character
	 *            字符编码，可以是"UTF-8"(空值默认),"GB2312"( 文件的编码格式),"ISO8859-1"
	 * @return
	 */
	public Map<String, String> xmlPull(String xmlContent,
			List<String> paramsName, String character) {
		Map<String, String> map = new HashMap<String, String>();
		XmlPullParser parser = Xml.newPullParser();
		try {
			parser.setInput(str.getInputStream(xmlContent, character),
					character);
			int event = parser.getEventType();
			while (event != XmlPullParser.END_DOCUMENT) {
				switch (event) {
				case XmlPullParser.START_DOCUMENT:// 开始解析（第一次）
					break;
				case XmlPullParser.START_TAG:// 继续解析（第一次之后）
					for (int i = 0; i < paramsName.size(); i++) {
						if (paramsName.get(i).equals(parser.getName())) {
							map.put(paramsName.get(i), parser.nextText()
									.toString());
						}
					}
					break;
				case XmlPullParser.END_TAG:// 每一次解析结束时（每一次，即每一轮）
					break;
				}
				event = parser.next();
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			Log.e("test", "xml解析错误" + e.getMessage());
		}
		return map;
	}

}
